package com.bipbip.controlador;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.bipbip.beans.DatosLugar;
import com.bipbip.beans.DatosPublicacionForm;
import com.bipbip.modelo.Lugar;
import com.bipbip.modelo.MarcaVehiculo;
import com.bipbip.modelo.ModeloVehiculo;
import com.bipbip.modelo.NotificacionStandard;
import com.bipbip.modelo.Producto;
import com.bipbip.modelo.Publicacion;
import com.bipbip.modelo.Suscripcion;
import com.bipbip.modelo.Usuario;
import com.bipbip.modelo.Vehiculo;
import com.bipbip.modelo.Viaje;
import com.bipbip.service.EmpresaService;
import com.bipbip.service.MarcaService;
import com.bipbip.service.ModeloService;
import com.bipbip.service.NotificacionesFactory;
import com.bipbip.service.NotificacionesService;
import com.bipbip.service.PublicacionService;
import com.bipbip.service.SuscripcionService;
import com.bipbip.service.UsuarioService;
import com.bipbip.service.VehiculoService;

@Controller
@RequestMapping("/usuario")
@SessionAttributes({ "usuario", "publicacion", "viaje", "cabeceraDinamica",
		"lateralDinamico", "vehiculo" })
public class PanelUsuarioController {

	private static final Logger log = Logger
			.getLogger(PanelUsuarioController.class);

	@Autowired
	PublicacionService publicacionService;

	@Autowired
	VehiculoService vehiculoService;

	@Autowired
	SuscripcionService subscripcionService;

	@Autowired
	MarcaService marcaService;

	@Autowired
	ModeloService modeloService;

	@Autowired
	private PublicacionService pubServ;

	@Autowired
	private NotificacionesService notificacionesService;

	@Autowired
	EmpresaService empServ;

	@Autowired
	UsuarioService uServ;

	@Autowired
	SuscripcionService suscripcionService;

	@RequestMapping(value = "/Suscribirse/{idViaje}", method = RequestMethod.GET)
	public String suscribirseAViaje(@PathVariable("idViaje") int idViaje,
			Model model) {
		Publicacion publicacion = pubServ.obtenerPorID(idViaje);
		model.addAttribute("publicacion", publicacion);
		model.addAttribute("viaje", publicacion.getViaje());
		return "suscribirseAViaje";
	}

	@RequestMapping(value = "/ResponderSolicitud/{idSuscripcion}", method = RequestMethod.GET)
	public String responderSuscripcion(
			@PathVariable("idSuscripcion") int idSuscripcion, Model model) {
		Suscripcion suscripcion = suscripcionService
				.getSuscripcionById(idSuscripcion);
		Usuario usuario = uServ.getUsuarioById(suscripcion.getIdSolicitante());
		model.addAttribute("suscripcion", suscripcion);
		model.addAttribute("solicitante", usuario);

		return "responderSuscripcion";
	}

	@RequestMapping(value = "/AceptarSolicitud/{idSuscripcion}", method = RequestMethod.GET)
	public String aceptarSuscripcion(
			@PathVariable("idSuscripcion") int idSuscripcion, Model model) {
		Suscripcion suscripcion = suscripcionService
				.getSuscripcionById(idSuscripcion);
		Usuario solicitante = uServ.getUsuarioById(suscripcion
				.getIdSolicitante());
		Publicacion publicacion = publicacionService.obtenerPorID(suscripcion
				.getIdPublicacion());
		Usuario usuarioQuePublico = uServ.getUsuarioById(publicacion
				.getUsuario());
		suscripcion.setEstado("aceptada");
		suscripcionService.guardarSuscripcion(suscripcion);
		NotificacionStandard notificacion = (new NotificacionesFactory())
				.crearNotificacionAceptarSuscripcion(usuarioQuePublico,
						suscripcion);
		notificacionesService.guardarNotificacion(notificacion);
		return "redirect:/";
	}

	@RequestMapping(value = "/RechazarSolicitud/{idSuscripcion}", method = RequestMethod.GET)
	public String rechazarSuscripcion(
			@PathVariable("idSuscripcion") int idSuscripcion, Model model) {
		Suscripcion suscripcion = suscripcionService
				.getSuscripcionById(idSuscripcion);
		Usuario solicitante = uServ.getUsuarioById(suscripcion
				.getIdSolicitante());
		Publicacion publicacion = publicacionService.obtenerPorID(suscripcion
				.getIdPublicacion());
		Usuario usuarioQuePublico = uServ.getUsuarioById(publicacion
				.getUsuario());
		suscripcion.setEstado("rechazada");
		suscripcionService.guardarSuscripcion(suscripcion);
		NotificacionStandard notificacion = (new NotificacionesFactory())
				.crearNotificacionRechazarSuscripcion(usuarioQuePublico,
						suscripcion);
		notificacionesService.guardarNotificacion(notificacion);
		return "redirect:/";
	}

	@RequestMapping(value = "/ProcesarSuscripcion", method = RequestMethod.POST)
	public String procesarSuscripcion(@RequestParam String origen,
			@RequestParam String destino, @RequestParam String fecha,
			@RequestParam String comentarios, Publicacion publicacion,
			Viaje viaje, Usuario user, Model model) {
		if (subscripcionService.suscribirUsuarioEnViaje(user, publicacion,
				viaje)) {
			Suscripcion suscripcion = new Suscripcion();
			suscripcion.setIdPublicacion(publicacion.getId());
			suscripcion.setIdSolicitante(user.getId());
			suscripcion.setEstado("pendiente");
			suscripcion.setTitulo("titulo");
			suscripcionService.guardarSuscripcion(suscripcion);
			NotificacionesFactory factory = new NotificacionesFactory();
			notificacionesService.guardarNotificacion(factory
					.crearNotificacionDeSuscripcionAPublicacionDeViaje(
							publicacion, user, suscripcion));
			return "exito";
		} else {
			return "fracaso";
		}
	}

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String panel(Model model, Usuario usuario) {
		if (usuario != null && usuario.esEmpresarial()) {
			model.addAttribute("cabeceraDinamica",
					"/WEB-INF/views/panelUsuario/cabeceraEmpresarial.jsp");
			model.addAttribute("lateralDinamico", "/WEB-INF/views/blanco.jsp");
		} else {
			model.addAttribute("cabeceraDinamica",
					"/WEB-INF/views/cabecera.jsp");
			model.addAttribute("lateralDinamico",
					"/WEB-INF/views/panelUsuario/publicidad.jsp");
		}
		List<Vehiculo> misVehiculos = vehiculoService.obtenerVehiculos(usuario);
		List<VehiculoForm> vehiculos = new ArrayList<PanelUsuarioController.VehiculoForm>();
		for (Vehiculo v : misVehiculos) {
			vehiculos.add(new VehiculoForm(v));
		}
		List<Publicacion> misPubs = pubServ.obtenerTodos();
		log.info("Leidas " + misPubs.size() + " publicaciones");
		model.addAttribute("misPublicaciones", misPubs);
		model.addAttribute("vehiculos", vehiculos);
		model.addAttribute("user", usuario);
		return "panelUsuario";
	}

	@RequestMapping(value = "/MisViajes", method = RequestMethod.GET)
	public String misViajes(Model model, Usuario usuario) {
		List<Publicacion> misPubs = pubServ.obtenerPorUsuario(usuario);
		log.info("Leidas " + misPubs.size() + " publicaciones");
		model.addAttribute("misPublicaciones", misPubs);
		model.addAttribute("user", usuario);

		List<Vehiculo> misVehiculos = vehiculoService.obtenerVehiculos(usuario);
		List<VehiculoForm> vehiculos = new ArrayList<PanelUsuarioController.VehiculoForm>();
		for (Vehiculo v : misVehiculos) {
			vehiculos.add(new VehiculoForm(v));
		}
		model.addAttribute("vehiculos", vehiculos);
		return "misViajes";
	}

	@RequestMapping(value = "/MisSuscripciones", method = RequestMethod.GET)
	public String misSuscripciones(Model model, Usuario usuario) {
		List<Suscripcion> misSus = subscripcionService.selectByUsuario(usuario);
		log.info("Leidas " + misSus.size() + " suscripciones");
		model.addAttribute("misSuscripciones", misSus);
		model.addAttribute("user", usuario);
		return "misSuscripciones";
	}

	@RequestMapping(value = "/MisSuscripciones/{idSuscripcion}", method = RequestMethod.DELETE)
	public String borrarSuscripcion(Model model,
			@PathVariable Integer idSuscripcion, Usuario usuario) {
		Suscripcion s = subscripcionService.getSuscripcionById(idSuscripcion);

		NotificacionesFactory factory = new NotificacionesFactory();
		notificacionesService.guardarNotificacion(factory
				.crearNotificacionDeCancelacionDeSuscripcion(s, usuario,
						publicacionService.obtenerPorID(s.getIdPublicacion())
								.getUsuario()));

		subscripcionService.delete(s);
		List<Suscripcion> misSus = subscripcionService.selectByUsuario(usuario);
		log.info("Leidas " + misSus.size() + " suscripciones");
		model.addAttribute("misSuscripciones", misSus);
		model.addAttribute("user", usuario);
		return "misSuscripciones";
	}

	@RequestMapping(value = "/NuevoViaje", method = RequestMethod.GET)
	public String seleccionarVehiculo(Model model, Usuario user) {
		List<Vehiculo> misVehiculos = vehiculoService.obtenerVehiculos(user);
		List<VehiculoForm> vehiculos = new ArrayList<PanelUsuarioController.VehiculoForm>();
		for (Vehiculo v : misVehiculos) {
			vehiculos.add(new VehiculoForm(v));
		}
		model.addAttribute("misVehiculos", vehiculos);
		return "seleccionarVehiculo";
	}

	@RequestMapping(value = "/NuevoViaje", method = RequestMethod.POST)
	public String crearPublicacion(Model model, Usuario user,
			@RequestParam int idVehiculo) {
		Vehiculo vehiculo = vehiculoService.getVehiculo(idVehiculo);
		model.addAttribute("vehiculo", vehiculo);
		model.addAttribute("datosPublicacion", new DatosPublicacionForm());
		return "agregarPublicacion";
	}

	@RequestMapping(value = "/NuevoViaje", method = RequestMethod.POST, params = "nuevaPublicacion")
	public String procesarNuevaPablicacion(
			Model model,
			Usuario usuario,
			@ModelAttribute("datosPublicacion") @Valid DatosPublicacionForm formPublicacion,
			BindingResult result) {
		if (result.hasErrors()) {
			return "agregarPublicacion";
		}
		Publicacion publicacion = new Publicacion();
		Viaje viaje = new Viaje();
		viaje.setFechaFin(formPublicacion.getFechaFin());
		viaje.setFechaInicio(formPublicacion.getFechaInicio());
		publicacion.setViaje(viaje);
		publicacion.setUsuario(usuario.getId());
		publicacion.setFechaPosteo(new Date());
		publicacion.setMensaje(formPublicacion.getMensaje());
		publicacion.setTags(formPublicacion.getTags());
		publicacion.setTitulo(formPublicacion.getTitulo());
		publicacion.setDestacado(formPublicacion.isDestacado());
		// publicacion.setTipo(formPublicacion.getTipo());
		publicacion.setVehiculo(formPublicacion.getVehiculo());
		// pubServ.guardar(publicacion);
		model.addAttribute("viaje", viaje);
		model.addAttribute("fechaInicio", formPublicacion.getFechaInicio());
		model.addAttribute("fechaFin", formPublicacion.getFechaFin());
		model.addAttribute("publicacion", publicacion);
		model.addAttribute("datosLugar", new DatosLugar());
		model.addAttribute("isFirst", true);
		return "agregarViaje";

	}

	// Procesa los post con los puntos del viaje
	@RequestMapping(value = "/NuevoViaje", params = "punto", method = RequestMethod.POST)
	public String agregarPunto(
			@ModelAttribute("datosLugar") @Valid DatosLugar lugar,
			BindingResult result, @ModelAttribute("viaje") Viaje viaje,
			Publicacion publicacion, Usuario usuario, Vehiculo vehiculo,
			Model model) {
		if (result.hasErrors()) {
			return "agregarViaje";
		}
		// se transforma el string en fecha
		SimpleDateFormat formatoDelTexto = new SimpleDateFormat("dd-MM-yyyy");
		Date fecha = null;
		try {
			fecha = formatoDelTexto.parse(lugar.getFecha());
		} catch (Exception ex) {
			log.error("Error en la fecha ", ex);
		}
		viaje.agregarLugar(lugar.getX(), lugar.getY(), lugar.getDireccion(),
				fecha);
		log.info("Punto agregado: x: " + lugar.getX() + " y: " + lugar.getY()
				+ " fecha: " + fecha);
		model.addAttribute("viaje", viaje);
		String inicio = String.format("%02d/%02d/%4d", viaje.getFechaInicio()
				.getDate(), viaje.getFechaInicio().getMonth() + 1, viaje
				.getFechaInicio().getYear() + 1900);
		String fin = String.format("%02d/%02d/%4d", viaje.getFechaFin()
				.getDate(), viaje.getFechaFin().getMonth() + 1, viaje
				.getFechaFin().getYear() + 1900);
		model.addAttribute("fechaInicio", inicio);
		model.addAttribute("fechaFin", fin);
		model.addAttribute("lugar", new Lugar());
		if (lugar.isUltimo()) {
			publicacion.setFechaPosteo(new Date());
			viaje.setVehiculo(vehiculo);
			viaje.setPublicacion(publicacion);
			publicacion.setViaje(viaje);
			publicacion.setUsuario(usuario.getId());
			publicacion.setVehiculo(vehiculo.getId());
			publicacionService.guardar(publicacion);
			log.info("Viaje cargado");
			List<Publicacion> misPubs = pubServ.obtenerTodos();
			model.addAttribute("misPublicaciones", misPubs);
			return "panelUsuario";
			// TODO return una pantalla de exito de publicacion
		} else {
			return "agregarViaje";
		}
	}

	@RequestMapping(value = "/vehiculos", method = RequestMethod.GET)
	public String misVehiculos(Model model, Usuario user) {
		List<Vehiculo> misVehiculos = vehiculoService.obtenerVehiculos(user);
		List<VehiculoForm> vehiculos = new ArrayList<PanelUsuarioController.VehiculoForm>();
		for (Vehiculo v : misVehiculos) {
			vehiculos.add(new VehiculoForm(v));
		}
		model.addAttribute("marcaService", marcaService);
		model.addAttribute("modeloService", modeloService);
		model.addAttribute("misVehiculos", vehiculos);
		return "misVehiculos";
	}

	@RequestMapping(value = "/vehiculo", method = RequestMethod.GET)
	public String nuevoVehiculo(Model model, Usuario user) {
		List<ModeloVehiculo> modelos = modeloService.getAll();
		List<MarcaVehiculo> marcas = marcaService.getAll();
		model.addAttribute("vehiculo", new Vehiculo());
		model.addAttribute("marcas", marcas);
		model.addAttribute("modelos", modelos);

		return "agregarVehiculo";
	}

	@RequestMapping(value = "/vehiculo", method = RequestMethod.POST)
	public String procesarAltaVehiculo(HttpSession session,
			@Valid Vehiculo vehiculo) {
		vehiculo.setUsuario(((Usuario) session.getAttribute("usuario")).getId());
		vehiculoService.guardar(vehiculo);
		return "redirect:../vehiculos";
	}

	@RequestMapping(value = "/vehiculo/{idVehiculo}", method = RequestMethod.GET)
	public String nuevoVehiculo(@PathVariable Integer idVehiculo, Model model,
			Usuario user) {
		List<MarcaVehiculo> marcas = marcaService.getAll();
		model.addAttribute("vehiculo", vehiculoService.getVehiculo(idVehiculo));
		model.addAttribute("marcas", marcas);

		return "agregarVehiculo";
	}

	@RequestMapping(value = "/vehiculo/{idVehiculo}", method = RequestMethod.POST)
	public String procesarModificacionVehiculo(
			@PathVariable Integer idVehiculo, HttpSession session,
			@Valid Vehiculo vehiculo) {
		vehiculo.setUsuario(((Usuario) session.getAttribute("usuario")).getId());
		vehiculo.setId(idVehiculo);
		vehiculoService.guardar(vehiculo);
		return "redirect:../vehiculos";
	}

	@RequestMapping(value = "/vehiculo/{idVehiculo}", method = RequestMethod.DELETE)
	public String eliminarVehiculo(@PathVariable Integer idVehiculo,
			Model model, Usuario user) {
		vehiculoService.borrar(idVehiculo);
		return "redirect:../vehiculos";
	}

	public class VehiculoForm {
		Vehiculo v;

		public VehiculoForm(Vehiculo v) {
			this.v = v;
		}

		public String getModelo() {
			return modeloService.getModelo(v).getNombre();
		}

		public String getMarca() {
			return marcaService.getMarca(v).getNombre();
		}

		public Integer getPlazas() {
			return v.getPlazas();
		}

		public Integer getAnio() {
			return v.getAnio();
		}

		public Integer getId() {
			return v.getId();
		}

	}

	@RequestMapping(value = "/empresa", method = RequestMethod.GET)
	public String miEmpresa(Model model, Usuario user) {
		user.setIdEmpresa(uServ.getUsuarioById(user.getId()).getIdEmpresa());
		model.addAttribute("empresas", empServ.getAll());
		return "miEmpresa";
	}

	@RequestMapping(value = "/empresa/pendientes", method = RequestMethod.GET)
	public String miEmpresaPendientes(Model model, Usuario user) {
		if (user.getIdProducto() != Producto.enterprise) {
			return "redirect:../";
		}
		List<NotificacionStandard> nots = notificacionesService
				.getNotificacionesDelUsuario(user);
		List<NotificacionStandard> solicitudes = new ArrayList<NotificacionStandard>();
		for (NotificacionStandard n : nots) {
			if (n.getTipo() == NotificacionStandard.EMPLEO) {
				solicitudes.add(n);
				notificacionesService.deleteNotificacion(n);
			}
		}
		model.addAttribute("solicitudes", solicitudes);
		return "empresaPendientes";
	}

	@RequestMapping(value = "/empresa/admin", method = RequestMethod.GET)
	public String miEmpresaAdmin(Model model, Usuario user) {
		model.addAttribute("usuario", user);
		model.addAttribute("empleados",
				uServ.getUsuariosByEmpresa(user.getIdEmpresa()));
		return "empresaAdmin";
	}

	@RequestMapping(value = "/empresa/news", method = RequestMethod.GET)
	public String miEmpresaNews(Model model, Usuario user) {
		List<Publicacion> misPubs = pubServ.obtenerTodos();
		Iterator<Publicacion> it = misPubs.iterator();
		List<Publicacion> news = new ArrayList<Publicacion>();
		while (it.hasNext()) {
			Publicacion p = it.next();
			Integer pubUser = p.getUsuario();
			if (pubUser != null) {
				Usuario u = uServ.getUsuarioById(p.getUsuario());
				if (u.getIdEmpresa().equals(user.getIdEmpresa())) {
					news.add(p);
				}
			}
		}
		model.addAttribute("user", user);
		model.addAttribute("misPublicaciones", news);
		return "empresaNews";
	}
}
